#include "task.h"

#include "MemPool.h"
#include "scheduler.h"

// struct task  task_constructor()
void task_constructor(struct task *self)
{
    // struct task self ;
    self->ref_count_t = -1;
#ifdef REUSE_GRAPH
    self->backup_ref = -1;
    self->reused = 0;
    self->stored = 0;
    self->is_base_task = 1;
#endif
    self->affinity_id = INIT_AFFINITY;
#if defined(USE_PRIORITY_QUEUE) || defined(LOCAL_MULTI_PRIORI)
    self->priority_id = 0;
#endif
    // self->spawn_order_id = 0;
    self->next = NULL;
    // self->extra_state = 0;
    // return self;
}
struct task task_constructor_id(int id)
{
    struct task self;
    self.ref_count_t = -1;
#ifdef REUSE_GRAPH
    self.backup_ref = -1;
    self.reused = 0;
    self.stored = 0;
    self.is_base_task = 1;
#endif
    self.affinity_id = id;
#if defined(USE_PRIORITY_QUEUE) || defined(LOCAL_MULTI_PRIORI)
    self.priority_id = 0;
#endif
    // self.spawn_order_id = 0;
    self.next = NULL;
    // self.extra_state = 0;
    return self;
}

void increment_ref_count(struct task *self) { ++(self->ref_count_t); }
int ref_count(struct task *self) { return self->ref_count_t; }

#ifdef CONCURRENT_CONSTRUCT_GRAPH
/*
inline void set_pre(struct task* self,int p){self->pre = p;}
inline int pre_count(struct task *self){return self->pre;}
*/
#endif

// for dag reuse
#ifdef REUSE_GRAPH
void store_ref_count(struct task *self) { self->backup_ref = self->ref_count_t; }
void restore_ref_count(struct task *self) { self->ref_count_t = self->backup_ref; }

void set_stored(struct task *self, int flag) { self->stored = flag; }
int get_stored(struct task *self) { return self->stored; }

void set_reused_flag(struct task *self, int flag) { self->reused = flag; }
int get_reused_flag(struct task *self) { return self->reused; }
#endif

void set_affinity_id(struct task *self, int id) { self->affinity_id = id; }
#if defined(USE_PRIORITY_QUEUE) || defined(LOCAL_MULTI_PRIORI)
int get_priority_id(struct task *self) { return self->priority_id; }
void set_priority_id(struct task *self, int id) { self->priority_id = id; }
#endif
/*int get_spawn_order_id(struct task* self)
{
    return self->spawn_order_id;
}
void set_spawn_order_id(struct task* self,int id)
{
    self->spawn_order_id = id;
}*/

/*struct virtual_table_ * virtual_table_vptr = NULL;
void register_virtualfunc_table(virtual_table_*  p)
{
    virtual_table_vptr = p;
}*/

void wait_for_all(struct task *self) { main_kernel_func(self); }

void init_spawn(struct task *t) { init_spawn_sche(t); }

void enqueue(struct task *t) { enqueue(t); }

void spawn(struct task *t) { spawn_to_id(t); }

void adjust_affinity_id(struct task *self, struct task *another_task)
{
    if (self->affinity_id == INIT_AFFINITY) {
        self->affinity_id != another_task->affinity_id;
        return;
    }
    if (self->affinity_id != another_task->affinity_id) {
        self->affinity_id = FOLLOW_AFFINITY;
    }
}
struct empty_task *empty_task_constructor()
{
#ifdef MEMORY_POOL
#ifdef USE_SIMD
#ifdef TARG_SW5
    struct empty_task *self =
        (struct empty_task *)acemesh_myalloc_aligned_32(sizeof(struct empty_task));
#elif TARG_SW9
    struct empty_task *self =
        (struct empty_task *)acemesh_myalloc_aligned_64(sizeof(struct empty_task));
#endif
#else
    struct empty_task *self =
        (struct empty_task *)acemesh_myalloc_aligned_16(sizeof(struct empty_task));
#endif
#else
#ifdef TARG_SW5
    struct empty_task *self = (struct empty_task *)malloc(sizeof(struct empty_task));
#elif TARG_SW9
    // struct empty_task* self = (struct empty_task*)libc_uncached_aligned_malloc(sizeof(struct
    // empty_task));
    struct empty_task *self = (struct empty_task *)my_malloc_aligned(sizeof(struct empty_task));
#else
    assert(0);
#endif
#endif
#ifdef DEBUG
    printf("empty_task_addr=%p\n", self);
#endif
    task_constructor(&(self->task_base));
    return self;
}

void empty_task_destructor(struct empty_task *p_empty_task)
{
#ifndef MEMORY_POOL
#ifdef TARG_SW5
    free(p_empty_task);
#elif TARG_SW9
    // libc_uncached_aligned_free(p_empty_task);
    my_free_aligned(p_empty_task);
#else
    printf("losing free empty_task\n");
#endif
#endif
}
void setparent(struct task *child_task, struct task *t)
{
    child_task->parent = t;
    if (t != NULL) (t->_countdownToBeWokenUp)--;
}
struct task *getparent(struct task *t) { return t->parent; }
void initprecount(struct task *t)
{
    t->_predecessorCount = -1;
    t->_countdownToBeWokenUp = -1;
    t->_endExecute = 0;
    // t->countlock=0;
    // t->need_spawn_subtasks[NEED_SPAWN_SUBSIZE]=NULL;
}
void initialize(struct DataAccess *cur, int type, struct task *originator, int _accessFlags_, int top_) {
    //数据流收集时间缩短-->使用非常关键！！！！
    cur->_originator=originator;
    cur->_successor=NULL;//=nullptr;
    // cur->_child=NULL;//=nullptr;
    cur->_type=type;
    //cur->_weak_type=weak_type;
    cur->_accessFlags=_accessFlags_;
    cur->top=top_;
    cur->deleted=0;
    //cur->mutex_access=0;  //初始化位置改到这里会死锁
} 
// struct domain_hash *init_new_slave_table() {  //嵌套图时，主核对子图所要使用的哈希表分配内存和初始化
//     struct domain_hash *domain_slave_table;
//     domain_slave_table=(struct domain_hash *)acemesh_myalloc_aligned_32(sizeof(struct domain_hash));
//     domain_slave_table->domain_id=0;
//     domain_slave_table->hash=(struct new_slave_table *)acemesh_myalloc_aligned_32(SLAVE_TBL_SIZE*sizeof(struct new_slave_table));
    
//     struct new_slave_table *slave_table=domain_slave_table->hash;
//     slave_table->col_idx=0;
//     slave_table->items=(struct new_slave_table_item *)acemesh_myalloc_aligned_32(SLAVE_TBL_SIZE*sizeof(struct new_slave_table_item));
//     slave_table->col_items=(struct new_slave_table_item *)acemesh_myalloc_aligned_32(COLLISION_BUF_SIZE*sizeof(struct new_slave_table_item));

//     int i;
//     for (i = 0; i < SLAVE_TBL_SIZE; i++) {
//         slave_table->items[i].data_addr=NULL;
//         slave_table->items[i].data_access=NULL;
//         slave_table->items[i].succ=NULL;     
//     }   
//     int j;
//     for (j = 0; j < COLLISION_BUF_SIZE; j++) {
//         slave_table->col_items[j].data_addr=NULL;
//         slave_table->col_items[j].data_access=NULL;
//         slave_table->col_items[j].succ=NULL;
//     }
//     return slave_table;
// }

// struct new_slave_table *init_new_slave_table() {  //嵌套图时，主核对子图所要使用的哈希表分配内存和初始化
//     struct new_slave_table *slave_table;
//     slave_table=(struct new_slave_table *)acemesh_myalloc_aligned_32(sizeof(struct new_slave_table));
//     slave_table->col_idx=0;
//     slave_table->items=(struct new_slave_table_item *)acemesh_myalloc_aligned_32(SLAVE_TBL_SIZE*sizeof(struct new_slave_table_item));
//     slave_table->col_items=(struct new_slave_table_item *)acemesh_myalloc_aligned_32(COLLISION_BUF_SIZE*sizeof(struct new_slave_table_item));

//     int i;
//     for (i = 0; i < SLAVE_TBL_SIZE; i++) {
//         slave_table->items[i].data_addr=NULL;
//         slave_table->items[i].data_access=NULL;
//         slave_table->items[i].succ=NULL;     
//     }   
//     int j;
//     for (j = 0; j < COLLISION_BUF_SIZE; j++) {
//         slave_table->col_items[j].data_addr=NULL;
//         slave_table->col_items[j].data_access=NULL;
//         slave_table->col_items[j].succ=NULL;
//     }
//     return slave_table;
// }
void initTaskDataAccess(struct task *t, int _size)
{
    t->_dataAccesses._accessArray = acemesh_myalloc_aligned_32(sizeof(struct DataAccess) * _size);
    t->_dataAccesses._addressArray = acemesh_myalloc_aligned_32(sizeof(void *) * _size);
    //libc_uncached_aligned_malloc分配内存，性能非常非常慢（35倍），不建议使用
    //t->_dataAccesses._accessArray = libc_uncached_aligned_malloc(sizeof(struct DataAccess) * _size);
    //t->_dataAccesses._addressArray = libc_uncached_aligned_malloc(sizeof(void *) * _size);
    t->_dataAccesses._currentIndex = 0;
#ifdef SLAVE_BUILD
    t->_dataAccesses._subaccessBottomMap=init_new_slave_table();  //哈希表初始化
#else        
    t->_dataAccesses._subaccessBottomMap=NULL;
#endif
    //！！！扁平图任务不需要构造任务内的哈希表，需要关掉SLAVE_BUILD开关
    
}
struct TaskDataAccesses *getDataAccesses(struct task *t) { return &(t->_dataAccesses); }
struct DataAccess *findAccess(struct task *t, void *address)
{
    // if (_accessMap != nullptr) {
    // 	access_map_t::iterator itAccess = _accessMap->find(address);
    // 	if (itAccess != _accessMap->end())
    // 		return &itAccess->second;
    // } else {
    int size = t->_dataAccesses._currentIndex;
    for (size_t i = 0; i < size; ++i) {
        if (t->_dataAccesses._addressArray[i] == address)
            return &(t->_dataAccesses._accessArray[i]);
    }
    //}

    return NULL;
}
// void setChild(struct DataAccess *parent, struct DataAccess *child)
// {
//     // (parent->_child).store(child, std::memory_order_seq_cst);  //无法使用
//     parent->_child = child;
//     ((child->_originator)->_predecessorCount)--;
// }
void setSuccessor(struct DataAccess *pre, struct DataAccess *successor)
{
    // (pre->_successor).store(successor, std::memory_order_seq_cst);
    pre->_successor = successor;
     ((successor->_originator)->_predecessorCount)--;
    //  printf("前驱父任务%p,后继父任务%p\n",pre->_originator,successor->_originator)
}
void set_unblock_Successor(struct DataAccess *pre, struct DataAccess *successor)
{
    pre->_successor = successor;
}
int predec_count(struct task *t) { return t->_predecessorCount; }
int dec_predecessorCount(struct task *t)
{
    int res = (t->_predecessorCount -= 1);
    // assert(res >= 0);
    return (res == 0);
}
int child_count(struct task *t) { return t->_countdownToBeWokenUp; }
int dec_childCount(struct task *t)
{
    int res = (t->_countdownToBeWokenUp -= 1);
    // assert(res >= 0);
    return (res == 0);
}
int inc_predecessorCount(struct task *t) { t->_predecessorCount += 1; }
